/**
 * 描述：公共查询页面业务逻辑基础类
 * 路径：/framework/schema/component/Component.js
 * 作者：王鑫
 * 时间：2019-12-18
 */

import { mapGetters } from "vuex";
import { Column } from "./entity/Column";
import { ColumnButton } from "./entity/ColumnButton";
import { ModifyButton } from "./entity/ModifyButton";
import { MoreButton } from "./entity/MoreButton";
import { RemoveButton } from "./entity/RemoveButton";
import ViewProperty from './property';

export default {
  data() {
    return new ViewProperty(this)
  },

  computed: {
    ...mapGetters(['routePowers'])
  },

  methods: {

    onMounted() {
      if (this.hasOwnProperty('init')) {
        this.init();
      }
      this.working.exportable = this.hasPermission("export");
      this.working.editable = this.hasPermission("update");
      this.working.creatable = this.hasPermission("create");
      this.working.deletable = this.hasPermission("remove");

      // 判断是否需要操作列
      const { defaultActions, moreActions } = this.table.row;
      const { editable, deletable } = this.working;
      // 过滤拥有权限的 动作
      const default_actions = defaultActions.filter(p =>
        p.power && this.hasPermission(p.power.code)
      );
      // 过滤拥有权限的 更多动作
      const more_actions = moreActions.filter(p =>
        p.power && this.hasPermission(p.power.code)
      );

      if (editable || deletable || default_actions.length > 0 || more_actions.length > 0) {
        this.table.columns.push(
          this.generateColumn(default_actions, more_actions).build()
        );
      }

      this.table.columns.forEach(column => {
        if (column.title) {
          this.table.displayColumns.push({
            name: column.title,
            value: (!column.hidden)
          });
        }
      });

      // 获取 search-view 组件实例
      const view = this.$children[0];
      view.table = this.table;
      view.working = this.working;
      view.paper = this.paper;
      view.search = this.search;

      /**
       * 通用分页按钮点击事件处理
       * @param {number} index 调整后的页面索引
       */
      this.paper.pageChange = (index) => {
        this.search(this.table.filter, index);
      };
      /**
       * 通用页面大小改变事件处理
       * @param {number} size 调整后的分页大小
       */
      this.paper.sizeChange = size => {
        this.search(this.table.filter, 1, size);
      };
    },

    // #region 处理数据检索

    // interface
    queryData(params) {
      return Promise.reject({
        title: "系统故障",
        render(h) {
          return h('div', { class: "custom-notice" }, [
            h('div', '页面重写请求数据服务，无法请求接口'),
            h('div', { class: 'code-container' }, [
              h('div', 'methods :{'),
              h('div', { class: 'p1' }, 'queryData(params) {'),
              h('div', { class: 'p2' }, 'return new Promise();'),
              h('div', { class: 'p1' }, '}'),
              h('div', '}')
            ])
          ]);
        },
        duration: 0
      });
    },

    // interface
    /**
     * 遍历全部数据
     * @param {any[]} datas 数据
     */
    forEach(datas) { },

    // interface
    paramsAfter(params) { return params; },

    /**
     * 校验模块是否含有permission权限
     * @param {string} permission 权限码
     * @returns {boolean} 返回模块是否拥有权限
     */
    hasPermission(permission) {
      return !permission || this.routePowers.indexOf(permission) > -1;
    },

    /**
     * 创建数据过滤条件
     * @private
     * @param {JSON} filter 过滤条件
     * @param {number} index 页面索引
     * @param {number} size 分页大小
     */
    _generatorSearchFilter(filter, index, size) {
      let option = {};
      if (this.paper.enable) {
        option.page = index || this.paper.pageIndex || 1;
        option.pageSize = size || this.paper.pageSize || 10
      }
      if (filter) {
        Object.keys(filter).forEach((name, index) => {
          let value = filter[name];
          if (Array.isArray(value)) {
            let alias = this.table.filterAlias[name];
            if (Array.isArray(alias) && value[0] && value[1]) {
              option[alias[0]] = value[0].getTime() / 1000;
              option[alias[1]] = value[1].getTime() / 1000;
            }
          } else if (value) {
            option[name] = value;
          }
        });
      }
      if (this.paramsAfter && typeof this.paramsAfter === 'function') {
        option = this.paramsAfter(option);
      }
      return option;
    },

    /**
     * 通用查询方法：需在派生类中实现方法
     * @param {JSON} filter 查询条件
     * @param {number} index 页面索引
     * @param {number} size 分页大小
     */
    search(filter, index, size) {
      this.working.search = true;
      this.working.cancelSearch = true;
      this.table.loading = true;
      this.table.selectRowCount = 0;
      let params = this._generatorSearchFilter(filter, index, size);
      this.queryData(params)
        .then(({ data }) => {
          const { resultData } = data;
          if (resultData) {
            // 分页模式
            this.table.data = [...resultData];
            if (data.paginated) {
              // 分页模式-分页返回
              this.paper.pageCount = data.pageCount;
              this.paper.recordCount = data.recordCount;
              this.paper.pageSize = data.pageSize;
              this.paper.pageIndex = data.pageNumber;
            } else {
              // 分页模式-全部返回
              this.paper.recordCount = this.table.data.length;
            }
          } else {
            // 不分页模式
            this.table.data = data;
            this.paper.recordCount = data.length;
          }
          if (this.table.data) {
            this.table.data.forEach(p => this.forEach(p));
          }
        })
        .catch(this.$Error)
        .finally(() => {
          this.table.loading = false;
          this.working.search = false;
          this.working.cancelSearch = false;
        });
    },

    // #endregion

    // #region 处理数据新增
    /** 新增按钮点击事件处理 */
    onCreate() {
      if (this.route.create) {
        this.$router.push({ name: this.route.create });
      } else {
        this.editable.visible = true;
        this.editable.params = undefined;
      }
    },
    // #endregion

    // #region 处理数据编辑
    /**
     * 编辑按钮点击事件处理
     * @param {string} primaryKey 需要编辑的数据的主键
     * @returns {void}
     */
    onModify(primaryKey, rowData) {
      if (this.route.update) {
        this.$router.push({
          name: this.route.update,
          params: {
            id: primaryKey,
            data: rowData
          }
        });
      } else {
        this.editable.visible = true;
        this.editable.params = {
          id: primaryKey,
          data: rowData
        };
      }
    },
    // #endregion

    // #region 处理数据删除

    /**
     * 执行删除数据服务
     * @param {JSON} params 执行删除数据时传递的参数
     * @returns {Promise}
     */
    removeData(params) {
      return Promise.reject({
        title: "系统故障",
        render(h) {
          return h('div', { class: "custom-notice" }, [
            h('div', '页面重写删除数据服务，无法请求接口'),
            h('div', { class: 'code-container' }, [
              h('div', 'methods :{'),
              h('div', { class: 'p1' }, 'removeData(params) {'),
              h('div', { class: 'p2' }, 'return new Promise();'),
              h('div', { class: 'p1' }, '}'),
              h('div', '}')
            ])
          ]);
        },
        duration: 0
      });
    },

    /**
     * 执行批量删除操作
     * @private
     * @param {string[]} primaryKeyArray 需要批量删除的数据编号数组
     * @returns {void}
     */
    _executeRemoveAll(primaryKeyArray) {
      this.working.removes = true;
      let params = {};
      params[this.api.pkName] = primaryKeyArray.join(",")
      this.removeData(params)
        .then(() => {
          this.$Notice.success({ title: "操作成功", desc: `内容已被删除` });
          this.$nextTick(() => {
            this.search(this.table.filter);
          });
        })
        .catch(this.$Error)
        .finally(() => {
          this.working.removes = false;
        });
    },

    /**
     * 删除按钮点击事件处理
     * @param {string} primaryKey 需要删除的数据的主键
     * @returns {void}
     */
    onRemove(primaryKey) {
      this._executeRemoveAll([primaryKey]);
    },

    /**
     * 通用批量删除按钮点击事件处理
     * @param {JSON[]} datas 需要删除的数据清单
     * @returns {void}
     */
    onRemoveAll(datas) {
      let ids = [];
      if (datas instanceof Array) {
        ids = datas.map(p => p[this.api.pkName]);
      }
      this._executeRemoveAll(ids);
    },

    // #endregion

    // #region 处理数据导出

    /** 通用导出按钮点击事件处理 */
    onExport(table) {
      table.export({ filename: "数据" });
    },

    /** 通用导出按钮点击事件处理 */
    onExportAll(filter) {
      let params = this._generatorSearchFilter(filter);
      if (!this.exportData) {
        this.$Notice.warning({ title: "系统故障", desc: `未设置导出接口地址，无法请求接口` });
        return;
      }
      this.exportData(params)
        .then(res => {
          window.open(res.data);
        })
        .catch(this.$Error);
    },
    // #endregion

    /**
     * 生成操作列
     * @param {JSON[]} defaultActions -
     * @param {JSON[]} moreActions -
     */
    generateColumn(defaultActions, moreActions) {
      return new Column()
        .sort(false)
        .title(this.table.row.title)
        .align(this.table.row.align)
        .width(this.table.row.width)
        .fixed(this.table.row.fixed)
        .render((h, params) => {
          let domArray = [];
          // 编辑按钮
          if (this.working.editable) {
            domArray.push(
              new ModifyButton(h, params, this.onModify)
            );
          }
          // 删除按钮
          if (this.working.deletable) {
            domArray.push(
              new RemoveButton(h, params, this.onRemove, this.working.removeNotice)
            );
          }
          if (defaultActions.length > 0) {
            defaultActions.forEach(action => {
              const { power, click } = action;
              // before 属性用于验证记录是否可以显示，参数为行数据，返回boolean
              if (typeof action.before === 'function' && !action.before(params.row)) {
                return;
              }
              // confirm 是否需要二次确认
              if (action.confirm) {
                let title = "";
                if (typeof action.confirm.title === 'function') {
                  title = action.confirm.title(params.row);
                } else {
                  title = action.confirm.title;
                }
                const props = {
                  title,
                  confirm: true,
                  transfer: true
                };
                const on = {
                  "on-ok": () => { click(params.row) }
                }
                domArray.push(h("Poptip", { props, on }, [
                  new ColumnButton(h, power.text, power.icon).build()
                ]));
              } else {
                domArray.push(
                  new ColumnButton(h, power.text, power.icon)
                    .click(() => { click(params.row) })
                    .build()
                );
              }
            });
          }
          // 更多按钮
          if (moreActions.length > 0) {
            let button = new MoreButton(h, params, moreActions);
            button.hasOwnProperty("context") && domArray.push(button);
          }
          return h("div", { style: { display: 'inline-flex' } }, domArray);
        });
    }
  }
};
